/**
 * 304. 二维区域和检索 - 矩阵不可变
 * https://leetcode-cn.com/problems/range-sum-query-2d-immutable/
 */
public class Solutions_304 {
    public static void main(String[] args) {
        int[][] matrix = {{3, 0, 1, 4, 2},
                          {5, 6, 3, 2, 1},
                          {1, 2, 0, 1, 5},
                          {4, 1, 0, 1, 7},
                          {1, 0, 3, 0, 5}};

        NumMatrix obj = new NumMatrix(matrix);
//        int res1 = obj.sumRegion(2, 1, 4, 3);  // output: 8
//        System.out.println(res1);

//        int res2 = obj.sumRegion(1, 1, 2, 2);  // output: 11
//        System.out.println(res2);

        int res3 = obj.sumRegion(1, 2, 2, 4);  // output: 12
        System.out.println(res3);
    }
}

class NumMatrix {
    private int[][] memo = null;

    public NumMatrix(int[][] matrix) {
        if (matrix == null || matrix.length < 1 || matrix[0].length < 1) {
            return;
        }
        int row = matrix.length, col = matrix[0].length;
        // 多增加一行一列，可以减少计算时的索引越界判断
        memo = new int[row + 1][col + 1];
        // 遍历矩阵，完成计算结果的记忆化
        // memo[2][2] = 14，表示左上角 [0, 0],右下角 [2 - 1, 2 - 1] 的子矩阵中，元素总和为 14
        for (int i = 1; i <= row; i++) {
            for (int j = 1; j <= col; j++) {
                memo[i][j] = memo[i - 1][j] + memo[i][j - 1] + matrix[i - 1][j - 1];
                // 减去重复计算的部分，因为行和列中都已经
                // 计算过了左上角 [0, 0]，右下角 [i - 1, j - 1] 的部分
                memo[i][j] -= memo[i - 1][j - 1];
            }
        }
    }

    public int sumRegion(int row1, int col1, int row2, int col2) {
        // 减去不在区域中的行矩阵和，和列矩阵和
        int res = memo[row2 + 1][col2 + 1] - memo[row1][col2 + 1] - memo[row2 + 1][col1];
        // 加上重复部分的值，即以左上角 [row1, col1] 的左上角为右下角的区域
        res += memo[row1][col1];
        return res;
    }
}
